package cloud.xlh.filter;

import cloud.xlh.infrastructure.cache.redis.utils.RedisUtil;
import cloud.xlh.infrastructure.utils.StringUtil;
import cloud.xlh.service.IdempotentHandleService;
import cloud.xlh.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * Created with IntelliJ IDEA.
 *
 * @ project name : xlh_osms
 * @ Author: XuLeHuang
 * @ Date: 2023/1/12 22:28
 * @ Description: 幂等性处理
 */
@Slf4j
@Component
public class IdempotentFilter implements GlobalFilter, Ordered {
    @Autowired
    private TokenService tokenService;

    @Value("${all-api-idempotent-handel}")
    private boolean allApiIdempotentHandel;

    @Value("${url.idempotentHandel.file.location}")
    private String urlLimitListFileLocation;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IdempotentHandleService idempotentHandleService;

    private static final String URL_LIMIT_KEY = "urlLimitKey";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("幂等性处理过滤器前置处理");
        writeCache();
        ServerHttpRequest request = exchange.getRequest();
        if (allApiIdempotentHandel) {
            String requestPath = request.getURI().getPath();
        } else {
            /*Idempotent idempotent = ((HandlerMethod) handler).getMethodAnnotation(Idempotent.class);
            if (idempotent == null) {
                return true;
            }*/
            String requestPath = request.getURI().getPath();
            boolean limitFlag = redisUtil.setIsMember(URL_LIMIT_KEY, requestPath);
            if (!limitFlag) {
                return chain.filter(exchange);
            }
        }
        // 获取到了方法上的注解，然后怎么办呢，我们就调用TokenService的验证方法，验证下，看是否符合条件
        boolean passed = idempotentHandleService.idempotentHandle(request);
        if (!passed) {
            return exchange.getResponse().setComplete();
        } else {
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                /**
                 * 后置处理
                 * */
                log.info("幂等性处理过滤器后置处理");
                idempotentHandleService.updateIdempotentKey(request);
            }));
        }
    }

    @Override
    public int getOrder() {
        return -500;
    }

    /**
     * 仅在程序运行的时候执行一次
     * todo
     * 如何动态监听url列表文件的变化
     */

    public void writeCache() {
        List<String[]> limitUrlList = getLimitUrlList();
        limitUrlList.stream().forEach(var1 -> {
            String value = var1[0];
            redisUtil.setAdd(URL_LIMIT_KEY, value);
        });
    }


    /**
     * 逗号分隔
     */
    public List<String[]> getLimitUrlList() {
        List<String[]> list = StringUtil.readFromCsvFile("D:\\development\\environment\\idea\\IdeaProjects\\xlh_osms\\gateway\\src\\main\\resources\\urllimit\\list.csv");
        return list;
    }
}
